package validator

import (
	"crypto"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"log/slog"
	"os"
	"time"
)

// LicenseInfo 许可证信息
type LicenseInfo struct {
	CustomerID  string    `json:"customer_id"`
	ProductID   string    `json:"product_id"`
	ExpiryDate  time.Time `json:"expiry_date"`
	MaxUsers    int       `json:"max_users"`
	LicenseType string    `json:"license_type"`
}

// LicenseValidator 许可证验证器
type LicenseValidator struct {
	publicKey     *rsa.PublicKey // 嵌入的公钥用于验证签名
	licensePath   string
	lastCheckTime time.Time
}

func NewLicenseValidator(
	publicKey *rsa.PublicKey,
	licensePath string,
	lastCheckTime time.Time,
) *LicenseValidator {
	return &LicenseValidator{
		publicKey,
		licensePath,
		lastCheckTime,
	}
}

// ValidateLicense 验证许可证
func (lv *LicenseValidator) ValidateLicense() (*LicenseInfo, error) {
	data, err := os.ReadFile(lv.licensePath)
	if err != nil {
		slog.Error("License: Failed to read the license file", "error", err, "license_path", lv.licensePath)
		return nil, fmt.Errorf("failed to read the license file: %w", err)
	}

	var signedLicense struct {
		Data      string `json:"data"`
		Signature string `json:"signature"`
	}

	if err := json.Unmarshal(data, &signedLicense); err != nil {
		slog.Error("License: Failed to parse the license file", "error", err)
		return nil, fmt.Errorf("failed to parse the license file: %w", err)
	}

	// 1. 验证RSA-PSS签名
	if err := lv.verifySignature(signedLicense.Data, signedLicense.Signature); err != nil {
		slog.Error("License: The license signature is invalid", "error", err)
		return nil, fmt.Errorf("the license signature is invalid: %w", err)
	}

	// 2. 解码许可证数据
	decoded, err := base64.StdEncoding.DecodeString(signedLicense.Data)
	if err != nil {
		slog.Error("License: Failed to decode the license data", "error", err)
		return nil, fmt.Errorf("failed to decode the license data: %w", err)
	}

	var licenseInfo LicenseInfo
	if err := json.Unmarshal(decoded, &licenseInfo); err != nil {
		slog.Error("License: Failed to parse the license information", "error", err)
		return nil, fmt.Errorf("failed to parse the license information: %w", err)
	}

	// 3. 检查过期时间
	if time.Now().After(licenseInfo.ExpiryDate) {
		slog.Error("License: The license has expired", "expiry_date", licenseInfo.ExpiryDate)
		return nil, errors.New("the license has expired")
	}

	lv.lastCheckTime = time.Now()
	return &licenseInfo, nil
}

// verifySignature 验证HMAC签名
func (lv *LicenseValidator) verifySignature(data, signature string) error {
	// 解码Base64签名
	sigBytes, err := base64.StdEncoding.DecodeString(signature)
	if err != nil {
		slog.Error("License: Signature decoding failed", "error", err)
		return fmt.Errorf("signature decoding failed: %w", err)
	}

	// 计算数据的SHA-256哈希值
	hasher := sha256.New()
	hasher.Write([]byte(data))
	hashed := hasher.Sum(nil)

	// 使用PSS模式验证签名
	return rsa.VerifyPSS(lv.publicKey, crypto.SHA256, hashed, sigBytes, &rsa.PSSOptions{
		SaltLength: rsa.PSSSaltLengthAuto,
		Hash:       crypto.SHA256,
	})
}

// IsTimeValid 检查时间是否被篡改
func (lv *LicenseValidator) IsTimeValid(ntpTime time.Time) bool {
	// 允许一定的网络延迟
	allowedDrift := time.Minute * 5
	currentTime := time.Now()

	// 检查系统时间是否在NTP时间合理范围内
	timeDiff := currentTime.Sub(ntpTime)
	if timeDiff < -allowedDrift || timeDiff > allowedDrift {
		slog.Error("License: The system time is outside the acceptable range for NTP", "system time", currentTime, "ntp_time", ntpTime)
		return false
	}

	// 检查时间是否回退
	if !lv.lastCheckTime.IsZero() && currentTime.Before(lv.lastCheckTime) {
		slog.Error("License: The system time is incorrect", "last_check_time", lv.lastCheckTime)
		return false
	}

	return true
}
